package com.cnebula.openapi.auth.provider;

import java.util.HashMap;
import java.util.Map;

import com.cnebula.openapi.auth.AuthOptions;
import com.cnebula.openapi.auth.service.ClientAppService;
import com.cnebula.openapi.auth.service.OAuthService;
import com.cnebula.openapi.auth.service.SignService;
import com.cnebula.openapi.auth.util.RestUtil;
import com.cnebula.openapi.auth.vo.AccessToken;
import com.cnebula.openapi.auth.vo.ResponseResult;

import io.vertx.core.Future;
import io.vertx.core.Vertx;
import io.vertx.ext.web.RoutingContext;
import io.vertx.redis.RedisClient;
import io.vertx.redis.RedisOptions;

public class LogoutProvider {

	private final AuthOptions options;
	private RedisClient redis;
	private SignService signService;
	private ClientAppService clientAppService;
	private OAuthService oauthService;

	public LogoutProvider(SignService signService, ClientAppService clientAppService, OAuthService oauthService, Vertx vertx, AuthOptions options) {
		this.options = options;
		redis = RedisClient.create(vertx, new RedisOptions());
		this.signService = signService;
		this.clientAppService = clientAppService;
		this.oauthService = oauthService;
	}

	public void logout(RoutingContext context) {
		Map<String, String> params = RestUtil.collectParams(context);

		// 验证必备参数
		Map<String, String> requiredParams = new HashMap<String, String>();
		requiredParams.put("client_key", params.get("client_key"));
		requiredParams.put("access_token", params.get("access_token"));
		requiredParams.put("tenant_id", params.get("tenant_id"));
		requiredParams.put("timestamp", params.get("timestamp"));
		requiredParams.put("sign", params.get("sign"));
		if (!RestUtil.checkRequired(requiredParams, context)) {
			return;
		}

		String clientKey = params.get("client_key");
		String tenantId = params.get("tenant_id");
		String sign = params.get("sign");
		String token = params.get("access_token");
		String timestamp = params.get("timestamp");
		
		Future<AccessToken> logoutFuture = Future.future();
		
		clientAppService.getClientApp(clientKey, tenantId).compose(clientApp ->{
			// 验证签名
			Future<Void> f = Future.future();
			try {
				Map<String, String> signParams = new HashMap<String, String>(params);
				signParams.remove("sign");
				signService.check(signParams, clientApp.clientSecret, Long.parseLong(timestamp), sign);
				f.complete();
			} catch (Exception e) {
				f.fail(e);
			}
			return f;
		}).compose(v -> {
			// 验证token
			oauthService.checkAccessToken(token).setHandler(h -> {
				if(h.succeeded()) {
					logoutFuture.complete(h.result());
				}else {
					logoutFuture.fail(h.cause());
				}
			});
		}, logoutFuture);
		
		
		//登出
		logoutFuture.setHandler(h -> {
			if(h.succeeded()) {
				AccessToken accessToken = h.result();
				redis.del(accessToken.token, r -> {
					if(r.succeeded()) {
						RestUtil.responseResult(new ResponseResult(), context);
					}else {
						RestUtil.responseError(r.cause(), context);
					}
				});
			}else {
				RestUtil.responseError(h.cause(), context);
			}
		});
		
	}
}
